package com.train.daily.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.train.daily.dto.station.DailyTrainStationQueryDTO;
import com.train.daily.resp.station.DailyTrainStationPageResp;
import com.train.common.enums.impl.BizExceptionEnums;
import com.train.common.exception.GlobalException;
import com.train.common.resp.CommonResp;
import com.train.common.resp.PageResp;
import com.train.daily.dto.station.DailyTrainStationAddOrEditDTO;
import com.train.daily.dto.station.DailyTrainStationDTO;
import com.train.daily.dto.station.DailyTrainStationPageDTO;
import com.train.daily.mapper.DailyTrainStationMapper;
import com.train.daily.po.DailyTrainStationPO;
import com.train.daily.resp.station.DailyTrainStationPageQueryResp;
import com.train.daily.resp.train.DailyTrainQueryResp;
import com.train.daily.service.DailyTrainService;
import com.train.daily.service.DailyTrainStationService;
import com.train.openfeign.core.utils.OpenFeignUtils;
import com.train.system.api.TrainApi;
import com.train.system.api.TrainStationApi;
import com.train.system.resp.trainstation.TrainStationListResp;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author baitiaojun
 * @description 针对表【dailyTrainStation(每日车站)】的数据库操作Service实现
 * @createDate 2025-03-01 14:35:49
 */
@Service
public class DailyTrainStationServiceImpl extends ServiceImpl<DailyTrainStationMapper, DailyTrainStationPO>
    implements DailyTrainStationService {

    private final DailyTrainStationMapper dailyTrainStationMapper;

    private final TrainStationApi trainStationFacade;

    private final TrainApi trainApi;

    private final DailyTrainService dailyTrainService;

    public DailyTrainStationServiceImpl(DailyTrainStationMapper dailyTrainStationMapper,
                                        @Qualifier("com.train.system.api.TrainStationApi") TrainStationApi trainStationFacade,
                                        @Qualifier("com.train.system.api.TrainApi") TrainApi trainApi,
                                        @Lazy DailyTrainService dailyTrainService) {
        this.dailyTrainStationMapper = dailyTrainStationMapper;
        this.trainStationFacade = trainStationFacade;
        this.trainApi = trainApi;
        this.dailyTrainService = dailyTrainService;
    }

    @Override
    public void addOrEditDailyTrainStation(DailyTrainStationAddOrEditDTO dailyTrainStationAddOrEditDTO) {
        //校验车次是否存在
        CommonResp resp = trainApi.validTrainCodeList(dailyTrainStationAddOrEditDTO.getTrainCode());
        if (!OpenFeignUtils.isSuccess(resp)) {
            throw new GlobalException(BizExceptionEnums.EXP_TRAIN_CODE_NOT_EXISTS);
        }

        if (dailyTrainStationAddOrEditDTO.getId() != null) {
            //如果是编辑,需要校验id记录是否存在
            if (!dailyTrainStationMapper.existsId(dailyTrainStationAddOrEditDTO.getId())) {
                throw new GlobalException(BizExceptionEnums.EXP_DAILY_TRAIN_STATION_NOT_EXISTS);
            }

            //获取同一天里同车次下所有途经车站列表
            List<DailyTrainStationDTO> trainStationDTOList = dailyTrainStationMapper.getTrainStationList(dailyTrainStationAddOrEditDTO);

            //过滤掉被更新的途径站,收集为map
            Map<Integer, String> stationIndexNameMap = trainStationDTOList.stream()
                    .filter(trainStationDTO -> !trainStationDTO.getId().equals(dailyTrainStationAddOrEditDTO.getId()))
                    .collect(Collectors.toMap(DailyTrainStationDTO::getIndex, DailyTrainStationDTO::getName));

            //校验同车下其他途径车站的的站名或站序是否已存在
            if (stationIndexNameMap.containsKey(dailyTrainStationAddOrEditDTO.getIndex())
                    || stationIndexNameMap.containsValue(dailyTrainStationAddOrEditDTO.getName())) {
                throw new GlobalException(BizExceptionEnums.EXP_DAILY_TRAIN_STATION_EXISTS);
            }
        } else {
            //新增就直接判断同一天里同车次下是否有相同站序或站名
            if (dailyTrainStationMapper.exists(dailyTrainStationAddOrEditDTO)) {
                throw new GlobalException(BizExceptionEnums.EXP_DAILY_TRAIN_STATION_EXISTS);
            }
        }

        //计算停站时长
        Duration duration = Duration.between(dailyTrainStationAddOrEditDTO.getInTime(), dailyTrainStationAddOrEditDTO.getOutTime());
        if (duration.isNegative()) {
            duration = Duration.ofSeconds(duration.getSeconds() + 86400);
        }
        long hours = duration.toHours();
        long minutes = duration.toMinutes() % 60;
        long seconds = duration.getSeconds() % 60;
        LocalTime timeDifference = LocalTime.of((int) hours, (int) minutes, (int) seconds);
        dailyTrainStationAddOrEditDTO.setStopTime(timeDifference);

        DailyTrainStationPO dailyTrainStationPO = BeanUtil.copyProperties(dailyTrainStationAddOrEditDTO, DailyTrainStationPO.class);
        boolean isSaved = this.saveOrUpdate(dailyTrainStationPO);
        if (!isSaved) {
            throw new GlobalException(BizExceptionEnums.EXP_ADD_DAILY_TRAIN_STATION);
        }
    }

    @Override
    public PageResp<DailyTrainStationPageResp> pageList(DailyTrainStationPageDTO dailyTrainStationPageDTO) {
        return dailyTrainStationMapper.pageList(dailyTrainStationPageDTO);
    }

    @Override
    public void remove(Long id) {
        boolean isRemoved = this.removeById(id);
        if (!isRemoved) {
            throw new GlobalException(BizExceptionEnums.EXP_REMOVE_DAILY_TRAIN_STATION);
        }
    }

    @Override
    public void generateDailyTrainStation(String date, List<String> trainCodes) {
        //基础数据查询所有车站
        CommonResp resp = trainStationFacade.getTrainStationListByTrainCodes(trainCodes);

        //转换类型
        List<TrainStationListResp> trainStationList = OpenFeignUtils.getResultList(resp, TrainStationListResp.class);
        if (CollectionUtil.isEmpty(trainStationList)) {
            throw new GlobalException(BizExceptionEnums.EXP_TRAIN_STATION_NOT_EXISTS);
        }

        //删除当天车站
        if (dailyTrainStationMapper.existsTrainStation(LocalDate.parse(date), trainCodes)) {
            boolean isDeleted = dailyTrainStationMapper.deleteTrainStations(LocalDate.parse(date), trainCodes);
            if (!isDeleted) {
                throw new GlobalException(BizExceptionEnums.EXP_ADD_DAILY_TRAIN_STATION);
            }
        }

        //重新添加当天车次
        List<DailyTrainStationPO> dailyTrainStationPOS = BeanUtil.copyToList(trainStationList, DailyTrainStationPO.class);
        dailyTrainStationPOS.forEach(dailyTrainStationPO -> dailyTrainStationPO.setDate(LocalDate.parse(date)));
        boolean isSaved = this.saveBatch(dailyTrainStationPOS);
        if (!isSaved) {
            throw new GlobalException(BizExceptionEnums.EXP_ADD_DAILY_TRAIN_STATION);
        }
    }

    @Override
    public Map<String, Long> countDailyTrainStation(LocalDate parse, List<String> trainCodes) {
        Map<String, Long> countStationMap = new HashMap<>();
        for (String trainCode : trainCodes) {
            Long countStation = dailyTrainStationMapper.countDailyTrainStation(parse, trainCode);
            countStationMap.put(trainCode, countStation + 1);
        }
        return countStationMap;
    }

    @Override
    public PageResp<DailyTrainStationPageQueryResp> queryTrainStationList(DailyTrainStationQueryDTO dto) {
        //查询途径站
        PageResp<DailyTrainStationPageQueryResp> pageResp = dailyTrainStationMapper.pageList(dto);
        List<DailyTrainStationPageQueryResp> queryResp = pageResp.getData();

        //查询每日车次
        DailyTrainQueryResp dailyTrainQueryResp = dailyTrainService.queryTrainByTrainCodeDate(dto.getTrainCode(), dto.getDate());

        //构造出发站和终点站
        DailyTrainStationPageQueryResp start = new DailyTrainStationPageQueryResp();
        start.setIndex(0L);
        start.setName(dailyTrainQueryResp.getStart());
        start.setOutTime(dailyTrainQueryResp.getStartTime());

        DailyTrainStationPageQueryResp end = new DailyTrainStationPageQueryResp();
        end.setIndex(pageResp.getTotal() + 1);
        end.setName(dailyTrainQueryResp.getEnd());
        end.setInTime(dailyTrainQueryResp.getEndTime());

        queryResp.addAll(ListUtil.of(start, end));

        //重新添加总数量
        pageResp.setTotal(Convert.toLong(pageResp.getTotal() + 2));

        //排序车站
        queryResp.sort(Comparator.comparingLong(DailyTrainStationPageQueryResp::getIndex));

        return pageResp;
    }
}




